/*
 *       This file is part of VFC.
 *
 *        VFC is free software: you can redistribute it and/or modify
 *        it under the terms of the GNU General Public License as published by
 *        the Free Software Foundation, either version 3 of the License, or
 *        (at your option) any later version.
 *
 *        VFC is distributed in the hope that it will be useful,
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *        GNU General Public License for more details.
 *
 *        You should have received a copy of the GNU General Public License
 *        along with VFC.  If not, see <http://www.gnu.org/licenses/>.
 */


using System;
using System.Collections.Generic;
using System.Text;

namespace VFC.Nes.Cpu.Opcode
{
    class IndirectX : _IndirectX_
    {
        private static int tmp = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;

        public static void ADC()
        {
            tmp = Cpu.Register.A;
            tmp2 = Cpu.Memory.Read(GetAddress());
            tmp3 = Cpu.Register.GetCarryFlag();

            tmp4 = (Cpu.Register.A + (tmp2 + tmp3));
            Cpu.Register.A = tmp4 & 0xff;
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Flags.CheckForCarryFlag(tmp4);
            Flags.CheckForOverflowFlagADC(tmp, tmp2, Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void SBC()
        {
            tmp = Cpu.Register.A;
            tmp2 = Cpu.Memory.Read(GetAddress());
            tmp3 = Cpu.Register.GetCarryFlag();

            tmp4 = Cpu.Register.A - Math.Abs(tmp2 - (tmp3 == 1 ? 0 : 1));
            Cpu.Register.A = tmp4 & 0xff;
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Flags.CheckForCarryFlagInSBC(tmp4);
            Flags.CheckForOverflowFlagSBC(tmp, tmp2, Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void CMP()
        {
            tmp2 = Cpu.Memory.Read(GetAddress());
            tmp = Cpu.Register.A - tmp2;
            Flags.CheckForNegativeFlag(tmp);
            //Carry Flag
            if (Cpu.Register.A >= tmp2)
            {
                Cpu.Register.SetCarryFlag();
            }
            else
            {
                Cpu.Register.ClearCarryFlag();
            }
            //Zero Flag
            if (Cpu.Register.A == tmp2)
            {
                Cpu.Register.SetZeroFlag();
            }
            else
            {
                Cpu.Register.ClearZeroFlag();
            }
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void LDA()
        {
            Cpu.Register.A = Cpu.Memory.Read(GetAddress());
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void STA()
        {
            Cpu.Memory.Write(GetAddress(), Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void AND()
        {
            Cpu.Register.A &= Cpu.Memory.Read(GetAddress());
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void EOR()
        {
            Cpu.Register.A ^= Cpu.Memory.Read(GetAddress());
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }

        public static void ORA()
        {
            Cpu.Register.A |= Cpu.Memory.Read(GetAddress());
            Flags.CheckForZeroFlag(Cpu.Register.A);
            Flags.CheckForNegativeFlag(Cpu.Register.A);
            Cpu.Register.PC += Cpu.Core.Size[Cpu.Core._Opcode_];
        }
    }
}
